/**
 * Copyright (C) 2011 Domenico Briganti <dometec@gmail.com>
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *         http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

// CountInputStream.java
// $Id: CountInputStream.java,v 1.1 2008/03/03 14:23:40 briganti Exp $
// (c) COPYRIGHT MIT, INRIA and Keio, 2001.
// Please first read the full copyright statement in file COPYRIGHT.html

package it.webrules.deploymanager.webapp.utils;

import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;

/**
 * count the number of bytes read through the stream
 */
public class CountInputStream extends InputStream {

	private long count = 0;
	private long marked = -1;
	private InputStream is;
	private boolean withPercent = false;
	private OutputStream outputStream;
	private long totalLength = 0;
	private String[] progressivo = { "0%", ".", ".", ".", ".", "25%", ".", ".", ".", ".", "50%", ".", ".", ".", ".", "75%", ".", ".", ".",
			".", "100%" };
	private int progressivoIdx = 0;

	public CountInputStream(InputStream is) {
		this.is = is;
	}

	/**
	 * Scrive nell'outputstream un dettaglio del progressivo del caricamento:
	 * 0%....25%....50%....75%....100%
	 * 
	 * @param openStream
	 *            il file che viene letto
	 * @param outputStream
	 *            dove scrive le informazioni per il caricamento
	 * @param totalLength
	 *            la lunghezza totale del file che si sta leggendo
	 */
	public CountInputStream(InputStream openStream, OutputStream outputStream, long totalLength) {
		this(openStream);
		this.setPercOutput(outputStream, totalLength);
	}

	public void setPercOutput(OutputStream outputStream, long totalLength) {
		this.outputStream = outputStream;
		this.totalLength = totalLength;
		this.withPercent = true;
	}

	public void calcPerc() {
		long l = (count * progressivo.length) / totalLength;
		if (l > progressivoIdx && progressivoIdx < progressivo.length) {
			try {
				outputStream.write(progressivo[progressivoIdx].getBytes());
			} catch (IOException e) {
				e.printStackTrace();
			}
			progressivoIdx++;
		}
	}

	public void calcPercAll() {
		while (progressivoIdx < progressivo.length) {
			try {
				outputStream.write(progressivo[progressivoIdx].getBytes());
			} catch (IOException e) {
				e.printStackTrace();
			}
			progressivoIdx++;
		}
	}

	public int available() throws IOException {
		return is.available();
	}

	public boolean markSupported() {
		return is.markSupported();
	}

	public int read() throws IOException {
		int r = is.read();
		if (r > 0)
			count++;
		if (withPercent) {
			calcPerc();
			if (r == -1)
				calcPercAll();
		}
		return r;
	}

	public int read(byte[] b, int off, int len) throws IOException {
		int r = is.read(b, off, len);
		if (r > 0)
			count += r;
		if (withPercent) {
			calcPerc();
			if (r == -1)
				calcPercAll();
		}
		return r;
	}

	public long skip(long skipped) throws IOException {
		long l = is.skip(skipped);
		if (l > 0)
			count += l;
		if (withPercent) {
			calcPerc();
			if (l == 0 && skipped > 0)
				calcPercAll();
		}
		return l;
	}

	public void mark(int readlimit) {
		is.mark(readlimit);
		marked = count;
	}

	public void reset() throws IOException {
		is.reset();
		count = marked;
	}

	public void close() throws IOException {
		is.close();
	}

	/**
	 * get the actual number of bytes read
	 * 
	 * @return a long, the number of bytes read
	 */
	public long getBytesRead() {
		return count;
	}

}
